﻿namespace Home.Services
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.OData;
    using Microsoft.OData.Edm;

    public static class ODataHelper
    {
        public static string ToODataFormat(DateTimeOffset value)
        {
            return value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture) + "Z";
        }

        internal static IEnumerable<IEdmStructuralProperty> GetConcurrencyProperties(this IEdmEntityType type)
        {
            Debug.Assert(type != null);

            return from s in type.StructuralProperties()
                   where s.ConcurrencyMode == EdmConcurrencyMode.Fixed && s.Type.IsPrimitive()
                   select s;
        }

        internal static object GetPropertyValue(this EntityInstanceContext entityInstanceContext, string propertyName)
        {
            Debug.Assert(entityInstanceContext != null);
            Debug.Assert(!string.IsNullOrEmpty(propertyName));

            if (entityInstanceContext.EdmObject == null)
            {
                throw new InvalidOperationException("The property entityInstanceContext.EdmObject cannot be null.");
            }

            object result;
            if (entityInstanceContext.EdmObject.TryGetPropertyValue(propertyName, out result))
            {
                return result;
            }

            var edmType = entityInstanceContext.EdmObject.GetEdmType();
            if (edmType == null)
            {
                throw new InvalidOperationException("The return value of method entityInstanceContext.EdmObject.GetEdmType() cannot be null.");
            }

            throw new InvalidOperationException(string.Format("The property '{0}' was not found.", propertyName));
        }

        internal static IEdmTypeReference GetEdmTypeReference(this IEdmModel edmModel, Type clrType)
        {
            Debug.Assert(edmModel != null);
            Debug.Assert(clrType != null);

            // the real implementation of the method is very complex, we use reflection instead.
            var type = Type.GetType("System.Web.OData.Formatter.EdmLibHelpers, System.Web.OData");
            var method = type.GetMethod("GetEdmTypeReference", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, new[] { typeof(IEdmModel), typeof(Type) }, null);
            return (IEdmTypeReference)method.Invoke(null, new object[] { edmModel, clrType });
        }
    }
}
